package com.github.zhijieqing.socket.cluster.common.storage;


import com.github.zhijieqing.socket.cluster.common.node.SocketServerNode;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;

import javax.websocket.Session;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;

@Slf4j
public abstract class SessionClientStorage implements ClientStorage {

    @Getter
    private final static Map<String, List<Session>> sessionMap = new ConcurrentHashMap<>();
    @Getter
    private final Map<String, Set<String>> sessionClientCache = new ConcurrentHashMap<>();
    @Getter
    private final Map<String, Set<String>> clientSessionCache = new ConcurrentHashMap<>();
    @Getter
    private Set<String> currentNodeClientIds=new HashSet<>();

    public void put(String clientId, Session session) {
        List<Session> sessionList = getSessionList(clientId);
        sessionList.add(session);
        if (log.isDebugEnabled()) {
            log.info("WS【{}】有新的连接【{}】，总数为:{}", clientId, session.getId(), sessionList.size());
        }
    }

    public void remove(String clientId, Session session) {
        List<Session> sessionList = getSessionList(clientId);
        sessionList.remove(session);
        remove(clientId,session.getId());
    }

    public void remove(String clientId) {
        getSessionMap().remove(clientId);
    }

    @Override
    public boolean currentNodeContains(String clientId, SocketServerNode socketServerNode) {
        return !getSessionList(clientId).isEmpty();
    }

    public List<Session> getSessionList(String clientId) {
        List<Session> sessionList = getSessionMap().get(clientId);
        if (sessionList == null) {
            synchronized (sessionMap) {
                sessionList = getSessionMap().computeIfAbsent(clientId, k -> new CopyOnWriteArrayList<>());
            }
        }
        return sessionList;
    }

    public Set<String> getClientList(String sessionId) {
        Set<String> clientSet = getSessionClientCache().get(sessionId);
        if (clientSet == null) {
            synchronized (sessionClientCache) {
                clientSet = getSessionClientCache().computeIfAbsent(sessionId, k -> new HashSet<>());
            }
        }
        return clientSet;
    }
    public Set<String> getSessionIdSet(String clientId) {
        Set<String> sessionIdSet = getClientSessionCache().get(clientId);
        if (sessionIdSet == null) {
            synchronized (sessionClientCache) {
                sessionIdSet = getClientSessionCache().computeIfAbsent(clientId, k -> new HashSet<>());
            }
        }
        return sessionIdSet;
    }

    protected void put(String clientId, String sessionId) {
        getClientList(sessionId).add(clientId);
        getSessionIdSet(clientId).add(sessionId);
        if (log.isDebugEnabled()) {
            log.info("WS【{}】有新的连接【{}】，当前数量：{}", clientId, sessionId,getSessionIdSet(clientId).size());
        }
    }

    protected void remove(String clientId, String sessionId) {
        getClientList(sessionId).remove(clientId);
        getSessionIdSet(clientId).remove(sessionId);
        if (log.isDebugEnabled()) {
            log.info("WS【{}】有连接【{}】断开,当前数量：{}", clientId, sessionId,getSessionIdSet(clientId));
        }
    }
}
